﻿using DBUtil.MetaData;
using DotNetCommon.Extensions;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace DBUtil.Provider.SqlServer.MetaData
{
    /// <summary>
    /// SqlServer列
    /// </summary>
    public class SqlServerColumn : Column
    {
        /// <summary>
        /// 列类型
        /// </summary>
        public EnumSqlServerColumnType Type { set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.ORDINAL_POSITION
        /// </summary>
        public string ORDINAL_POSITION { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.DATA_TYPE
        /// </summary>
        public string DATA_TYPE { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.CHARACTER_MAXIMUM_LENGTH
        /// </summary>
        public string CHARACTER_MAXIMUM_LENGTH { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.NUMERIC_PRECISION
        /// </summary>
        public string NUMERIC_PRECISION { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.NUMERIC_PRECISION_RADIX
        /// </summary>
        public string NUMERIC_PRECISION_RADIX { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.NUMERIC_SCALE
        /// </summary>
        public string NUMERIC_SCALE { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.DATETIME_PRECISION
        /// </summary>
        public string DATETIME_PRECISION { internal set; get; }

        #region ConvertType 转换列类型
        internal void ConvertType()
        {
            var column = this;
            var type = DATA_TYPE;
            var maxLen = CHARACTER_MAXIMUM_LENGTH;
            var datetime_precision = DATETIME_PRECISION;
            var number_precision = NUMERIC_PRECISION;
            var number_scale = NUMERIC_SCALE;
            switch (type)
            {
                case "bit":
                    {
                        column.Type = EnumSqlServerColumnType.Bit;
                        column.TypeString = $"bit";
                        break;
                    }

                case "tinyint":
                    {
                        column.Type = EnumSqlServerColumnType.TinyInt;
                        column.TypeString = $"tinyint";
                        break;
                    }
                case "smallint":
                    {
                        column.Type = EnumSqlServerColumnType.SmallInt;
                        column.TypeString = $"smallint";
                        break;
                    }
                case "int":
                    {
                        column.Type = EnumSqlServerColumnType.Int;
                        column.TypeString = $"int";
                        break;
                    }
                case "bigint":
                    {
                        column.Type = EnumSqlServerColumnType.BigInt;
                        column.TypeString = "bigint";
                        break;
                    }

                case "float":
                    {
                        column.Type = EnumSqlServerColumnType.Float;
                        column.TypeString = $"float";
                        break;
                    }
                case "real":
                    {
                        column.Type = EnumSqlServerColumnType.Real;
                        column.TypeString = $"real";
                        break;
                    }
                case "numeric":
                    {
                        column.Type = EnumSqlServerColumnType.Numeric;
                        column.TypeString = $"numeric({number_precision},{number_scale})";
                        break;
                    }
                case "decimal":
                    {
                        column.Type = EnumSqlServerColumnType.Decimal;
                        column.TypeString = $"decimal({number_precision},{number_scale})";
                        break;
                    }

                case "smallmoney":
                    {
                        column.Type = EnumSqlServerColumnType.SmallMoney;
                        column.TypeString = $"smallmoney";
                        break;
                    }
                case "money":
                    {
                        column.Type = EnumSqlServerColumnType.Money;
                        column.TypeString = $"money";
                        break;
                    }



                case "char":
                    {
                        column.Type = EnumSqlServerColumnType.Char;
                        column.TypeString = $"char({maxLen})";
                        break;
                    }
                case "varchar":
                    {
                        column.Type = EnumSqlServerColumnType.VarChar;
                        column.TypeString = $"varchar({maxLen})";
                        if (maxLen == "-1")
                        {
                            column.TypeString = $"varchar(max)";
                        }
                        break;
                    }
                case "nchar":
                    {
                        column.Type = EnumSqlServerColumnType.NChar;
                        column.TypeString = $"nchar({maxLen})";
                        break;
                    }

                case "nvarchar":
                    {
                        column.Type = EnumSqlServerColumnType.NVarChar;
                        column.TypeString = $"nvarchar({maxLen})";
                        if (maxLen == "-1")
                        {
                            column.TypeString = $"nvarchar(max)";
                        }
                        break;
                    }
                case "text":
                    {
                        column.Type = EnumSqlServerColumnType.Text;
                        column.TypeString = $"text";
                        break;
                    }
                case "ntext":
                    {
                        column.Type = EnumSqlServerColumnType.NText;
                        column.TypeString = $"ntext";
                        break;
                    }


                case "binary":
                    {
                        column.Type = EnumSqlServerColumnType.Binary;
                        column.TypeString = $"binary({maxLen})";
                        break;
                    }
                case "image":
                    {
                        column.Type = EnumSqlServerColumnType.Image;
                        column.TypeString = $"image";
                        break;
                    }
                case "varbinary":
                    {
                        column.Type = EnumSqlServerColumnType.VarBinary;
                        column.TypeString = $"varbinary({maxLen})";
                        if (maxLen == "-1")
                        {
                            column.TypeString = $"varbinary(max)";
                        }
                        break;
                    }

                case "date":
                    {
                        column.Type = EnumSqlServerColumnType.Date;
                        column.TypeString = $"date";
                        break;
                    }
                case "datetime":
                    {
                        column.Type = EnumSqlServerColumnType.DateTime;
                        column.TypeString = $"datetime";
                        break;
                    }
                case "datetime2":
                    {
                        column.Type = EnumSqlServerColumnType.DateTime2;
                        column.TypeString = $"datetime2({datetime_precision})";
                        break;
                    }
                case "datetimeoffset":
                    {
                        column.Type = EnumSqlServerColumnType.DateTimeOffset;
                        column.TypeString = $"datetimeoffset({datetime_precision})";
                        break;
                    }
                case "smalldatetime":
                    {
                        column.Type = EnumSqlServerColumnType.SmallDateTime;
                        column.TypeString = $"smalldatetime";
                        break;
                    }
                case "time":
                    {
                        column.Type = EnumSqlServerColumnType.Time;
                        column.TypeString = $"time({datetime_precision})";
                        break;
                    }
                case "timestamp":
                    {
                        column.Type = EnumSqlServerColumnType.TimeStamp;
                        column.TypeString = $"timestamp";
                        break;
                    }

                case "geography":
                    {
                        column.Type = EnumSqlServerColumnType.Geography;
                        column.TypeString = $"geography";
                        break;
                    }
                case "geometry":
                    {
                        column.Type = EnumSqlServerColumnType.Geometry;
                        column.TypeString = $"geometry";
                        break;
                    }

                case "hierarchyid":
                    {
                        column.Type = EnumSqlServerColumnType.Hierarchyid;
                        column.TypeString = $"hierarchyid";
                        break;
                    }
                case "sql_variant":
                    {
                        column.Type = EnumSqlServerColumnType.SqlVariant;
                        column.TypeString = $"sql_variant";
                        break;
                    }
                case "uniqueidentifier":
                    {
                        column.Type = EnumSqlServerColumnType.UniqueIdentifier;
                        column.TypeString = $"uniqueidentifier";
                        break;
                    }

                case "xml":
                    {
                        column.Type = EnumSqlServerColumnType.Xml;
                        column.TypeString = $"xml";
                        break;
                    }
                default:
                    {
                        column.Type = EnumSqlServerColumnType.Other;
                        column.TypeString = type;
                        break;
                    }
            }
            TypeNum = (int)column.Type;
        }
        #endregion

        public static EnumSqlServerColumnType? ParseColumnType(string typeString)
        {
            if (typeString.IsNullOrEmptyOrWhiteSpace()) return null;
            typeString = typeString.ToLower().Trim();
            if (typeString.StartsWith("bit")) return EnumSqlServerColumnType.Bit;

            if (typeString.StartsWith("tinyint")) return EnumSqlServerColumnType.TinyInt;
            if (typeString.StartsWith("smallint")) return EnumSqlServerColumnType.SmallInt;
            if (typeString.StartsWith("bigint")) return EnumSqlServerColumnType.BigInt;
            if (typeString.StartsWith("int")) return EnumSqlServerColumnType.Int;

            if (typeString.StartsWith("float")) return EnumSqlServerColumnType.Float;
            if (typeString.StartsWith("real")) return EnumSqlServerColumnType.Real;
            if (typeString.StartsWith("numeric")) return EnumSqlServerColumnType.Numeric;
            if (typeString.StartsWith("decimal")) return EnumSqlServerColumnType.Decimal;

            if (typeString.StartsWith("smallmoney")) return EnumSqlServerColumnType.SmallMoney;
            if (typeString.StartsWith("money")) return EnumSqlServerColumnType.Money;

            if (typeString.StartsWith("char")) return EnumSqlServerColumnType.Char;
            if (typeString.StartsWith("varchar")) return EnumSqlServerColumnType.VarChar;
            if (typeString.StartsWith("nchar")) return EnumSqlServerColumnType.NChar;
            if (typeString.StartsWith("nvarchar")) return EnumSqlServerColumnType.NVarChar;
            if (typeString.StartsWith("text")) return EnumSqlServerColumnType.Text;
            if (typeString.StartsWith("ntext")) return EnumSqlServerColumnType.NText;

            if (typeString.StartsWith("binary")) return EnumSqlServerColumnType.Binary;
            if (typeString.StartsWith("image")) return EnumSqlServerColumnType.Image;
            if (typeString.StartsWith("varbinary")) return EnumSqlServerColumnType.VarBinary;

            if (typeString.StartsWith("datetimeoffset")) return EnumSqlServerColumnType.DateTimeOffset;
            if (typeString.StartsWith("datetime2")) return EnumSqlServerColumnType.DateTime2;
            if (typeString.StartsWith("smalldatetime")) return EnumSqlServerColumnType.SmallDateTime;
            if (typeString.StartsWith("datetime")) return EnumSqlServerColumnType.DateTime;
            if (typeString.StartsWith("timestamp")) return EnumSqlServerColumnType.TimeStamp;
            if (typeString.StartsWith("date")) return EnumSqlServerColumnType.Date;
            if (typeString.StartsWith("time")) return EnumSqlServerColumnType.Time;

            if (typeString.StartsWith("geography")) return EnumSqlServerColumnType.Geography;
            if (typeString.StartsWith("geometry")) return EnumSqlServerColumnType.Geometry;
            if (typeString.StartsWith("hierarchyid")) return EnumSqlServerColumnType.Hierarchyid;
            if (typeString.StartsWith("sql_variant")) return EnumSqlServerColumnType.SqlVariant;
            if (typeString.StartsWith("uniqueidentifier")) return EnumSqlServerColumnType.UniqueIdentifier;
            if (typeString.StartsWith("xml")) return EnumSqlServerColumnType.Xml;

            return null;

        }
    }
}
